package com.lab.book.web.controller;

import com.lab.book.common.bean.LoginDetail;
import com.lab.book.common.bean.LoginHistory;
import com.lab.book.common.bean.User;
import com.lab.book.common.dto.LoginUserDTO;
import com.lab.book.common.dto.SearchUserDTO;
import com.lab.book.common.enums.UserEnum;
import com.lab.book.common.service.UserService;
import com.lab.book.common.validation.group.LoginGroup;
import com.lab.book.common.validation.group.RegisterGroup;
import com.lab.book.common.validation.group.SearchGroup;
import com.lab.book.web.message.LoginHistorySender;
import com.lab.cloud.common.utils.JWTUtils;
import com.lab.cloud.common.utils.R;
import com.lab.cloud.common.validation.group.*;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.util.*;

@Api(tags = "用户接口")
@Slf4j
@RestController
@RequestMapping
public class BookController {
    @Reference(timeout = 4000999)
    private UserService userService;

    @Autowired
    private LoginHistorySender loginHistorySender;

    @ApiOperation(hidden = false, httpMethod = "POST", value = "用户搜索", consumes = "application/json")
    @ApiResponses({
            @ApiResponse(code = 555, message = "参数验证未通过,具体查看数据信息"),
            @ApiResponse(code = 100, message = "搜索成功"),
            @ApiResponse(code = 8, message = "此人资料没有权限搜索")
    })
    @PostMapping("/searchUser")
    public R searchUser(@Validated(value = {SearchGroup.class}) @RequestBody(required = true) SearchUserDTO searchUserDTO,
                        BindingResult result) throws Exception {
        List<FieldError> errors = result.getFieldErrors();
        if (!CollectionUtils.isEmpty(errors)) return R.error(errors.get(0).getDefaultMessage());

        List<User> listUser = userService.queryUserList(searchUserDTO);
        return R.ok().put("items", listUser);
    }

    @ApiOperation(httpMethod = "POST", value = "用户登录", consumes = "application/json")
    @ApiResponses({
            @ApiResponse(code = 555, message = "参数验证未通过,具体查看数据信息"),
            @ApiResponse(code = 6, message = "用户名不存在"),
            @ApiResponse(code = 3, message = "用户名和密码不匹配"),
            @ApiResponse(code = 7, message = "登录成功")
    })
    //@PostMapping("/login")
    public R login(HttpServletRequest request, @Validated(value = {LoginGroup.class}) @RequestBody(required = true) LoginUserDTO loginUserDTO,
                   BindingResult result) throws Exception {
        List<FieldError> errors = result.getFieldErrors();
        if (!CollectionUtils.isEmpty(errors)) return R.error(errors.get(0).getDefaultMessage());

        String name = loginUserDTO.getName();
        String password = loginUserDTO.getPassword();

        LoginHistory loginHistory = null;
        String ip = request.getRemoteAddr();
        String userAgent = request.getHeader("User-Agent");

        User existUser = userService.existUser(name);
        // 用户不存在
        if (null == existUser) {
            return R.error(UserEnum.NoExist.getDesc());
        }

        // 账号，密码不匹配
        if (!new BCryptPasswordEncoder().matches(password, existUser.getPassword())) {
            loginHistory = constructLoginHistory(existUser.getName(), 1, ip, userAgent, false, UserEnum.Matching.getDesc());
            loginHistorySender.sendLoginHistory(loginHistory);

            return R.error(UserEnum.Matching.getDesc());
        }

        // 登录成功
        Map<String, Object> jwtMap = new HashMap<String, Object>();
        jwtMap.put("name", existUser.getName());

        //String jwt = jwtHelper.generateToken(jwtMap);
        //res.setData(jwt);
        //log.info("===========================> jwt : {}", jwt);

        // XXX 记录登录信息，RocketMQ, 监听方写入MongoDB
        loginHistory = constructLoginHistory(existUser.getName(), 0, ip, userAgent, true, UserEnum.LoginOK.getDesc());
        loginHistorySender.sendLoginHistory(loginHistory);

        return R.ok(UserEnum.LoginOK.getDesc());
    }

    @ApiOperation(httpMethod = "GET", value = "用户退出")
    //@GetMapping("/loginOut")
    public R loginOut() throws Exception {
        log.info("------> loginOut...");
        // TODO JWT 操作
        return null;
    }

    @ApiOperation(httpMethod = "POST", value = "用户注册")
    @ApiImplicitParams({@ApiImplicitParam(name = "name", value = "用户名", required = true, dataType = "String"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "String"),
            @ApiImplicitParam(name = "repwd", value = "确认密码", required = true, dataType = "String"),
            @ApiImplicitParam(name = "age", value = "年龄，大于等于18岁", required = true, dataType = "Integer"),
            @ApiImplicitParam(name = "sex", value = "性别 {'0':'男','1':'女','2':'人妖'}", required = true, dataType = "String"),
            @ApiImplicitParam(name = "email", value = "邮件地址", required = true, dataType = "Integer"),
            @ApiImplicitParam(name = "idno", value = "身份证号码", required = true, dataType = "String"),})
    //@PostMapping("/register")
    public R register(@Validated(value = {First.class, Second.class, Third.class, Fourth.class, Fifth.class,
            RegisterGroup.class}) User user, BindingResult result, Model model) throws Exception {
        List<FieldError> errors = result.getFieldErrors();
        if (!CollectionUtils.isEmpty(errors)) return R.error(errors.get(0).getDefaultMessage());

        if (!user.getPassword().equals(user.getRepwd())) {
            return R.error(UserEnum.PWDDif.getDesc());
        }

        user.setCreateTime(new Timestamp(new java.util.Date().getTime()));
        log.debug(user.toString());

        User existUser = this.userService.existUser(user.getName());
        if (null != existUser) {
            return R.error(UserEnum.Exist.getDesc());
        }

        try {
            user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
            user = this.userService.registerUser(user);
            return R.ok(UserEnum.Error.getDesc()).put("user", user);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.error(UserEnum.Error.getDesc());
        }
    }

    // 构建登录信息对象
    private LoginHistory constructLoginHistory(String username, Integer in1HourFailureTimes, String ip,
                                               String useragent, Boolean status, String message) {
        LoginHistory loginHistory = new LoginHistory();
        loginHistory.setUsername(username.toLowerCase());
        loginHistory.setLastLoginDate(new Date());
        loginHistory.setIn1HourFailureTimes(in1HourFailureTimes);

        LoginDetail detail = new LoginDetail();
        detail.setIp(ip);
        detail.setUserAgent(useragent);
        detail.setLoginDate(new Date());
        detail.setStatus(status);
        detail.setMessage(message);

        loginHistory.getDetails().add(detail);

        return loginHistory;
    }

    @ApiOperation(httpMethod = "GET", value = "资源123")
    @GetMapping("/r123")
    public R r123() throws Exception {
        String sub = JWTUtils.parseJWT(request.getHeader(HttpHeaders.AUTHORIZATION)).getSubject();
        log.info("------> sub...{}",sub);
        List<String> r123 = Arrays.asList("人民币", "美元", "欧元");
        return R.ok().put("data", r123);
    }

    @Autowired
    private HttpServletRequest request;
}
